// parse_FA_sequences.h
//

#if !defined(POSTGRES_FA_SEQUENCES_H)
#define POSTGRES_FA_SEQUENCES_H


#include <boost/tuple/tuple.hpp>
#include <vector>
#include <string>
#include <ctype.h>
#include <iosfwd>
#include "panda.h"
#include "stlhelper.h"
#include "progress_indicator.h"
#include <deque>
struct do_tolower
{
	static char* pbuf;
	char operator ()(char& c) const { return c = pbuf[(int)c];}
};
struct if_is_ascii
{
	static bool* pbuf;
	bool operator ()(char c) const { return pbuf[(int)c];}
};

inline void prepare_sequence(std::string& sequence)
{
	sequence.erase(transform_if(sequence.begin(), sequence.end(), sequence.begin(),
			do_tolower(), if_is_ascii()), sequence.end());
}

//***************************************************************************************

//		t_process_sequence

//***************************************************************************************
struct t_process_sequence
{
	t_process_sequence( bool							progress_dots_,
						const std::string&				db_origin_,
						std::vector<t_hash_id>&			acc_acchash_accid_current_,
						const t_progress_indicator&		progress_indicator_,
						std::ostream&					CERR_) :
			acc_acchash_accid_current(acc_acchash_accid_current_),
			acc_beg_line(0),
			count_seq(0),
			count_zero_length_sequences(0),
			dots(progress_indicator_),
			CERR(CERR_),
			db_origin(db_origin_)
		 {	}
	std::vector<t_hash_id>&			acc_acchash_accid_current;
	std::vector<t_hash_id_pos>		seq_seqhash_pi_pos_new;
	std::deque<t_id_pos>			acc_seqid_pos_extra;

	unsigned						acc_beg_line;
	unsigned						count_seq;
	unsigned						count_zero_length_sequences;
	unsigned						filepos_zero_length_sequence;
	t_progress_indicator			dots;
	std::ostream&					CERR;
	const std::string				db_origin;
	bool operator()(std::string accession, std::string& sequence,
						unsigned acc_filepos,
						unsigned seq_filepos);
};

inline void calculate_acc_hash(	const std::string::const_iterator&	str_beg,
										const std::string::const_iterator&	str_end,
										const t_digest&						hash,
										const std::string					db_origin,
										t_digest&						result)
{
	std::string temp (str_beg, str_end);
	temp.append((char*)&hash, sizeof(t_digest));
	temp += db_origin;
	digest_message(	temp.begin(), temp.end(), result );
}

typedef t_hash_id t_digest_taxid;
struct t_gi_taxid
{
	unsigned gi;
	unsigned taxid;
	t_gi_taxid(unsigned g, unsigned t = 0) :gi(g), taxid(t){}
};
inline bool operator < (const t_gi_taxid& a, const t_gi_taxid& b) { return a.gi < b.gi;}


bool parse_acc_data(const std::string&	acc,
					const std::string&	acc_code_regex_str,
					std::string&		acc_code,
					std::string&		acc_name);
bool parse_taxa(const std::string&	acc,
				const std::vector<t_digest_taxid>& hash_to_taxid,
				const std::vector<t_gi_taxid>& gi_to_taxid,
				std::string&		taxid);
bool parse_secIDs(const std::string& acc_line, std::vector<std::string>& vec_secids);


#endif		//POSTGRES_FA_SEQUENCES_H
